package server

import (
	"fmt"
	"log/slog"
	"net"

	"github.com/go-playground/validator/v10"
	"gitverse.ru/dlc/similarity-compiler/internal/config"
	"gitverse.ru/dlc/similarity-compiler/internal/interface/controllers/grpc/compiler"
	"gitverse.ru/dlc/similarity-compiler/pkg/api/grpc/proto"
	"gitverse.ru/dlc/similarity-compiler/pkg/errors"
	"google.golang.org/grpc"
)

type Controllers struct {
	Compiler *compiler.Controller
}

type DepsGRPC struct {
	Config config.GRPC  `validate:"required"`
	Logger *slog.Logger `validate:"required"`
}

type GRPC struct {
	Server *grpc.Server
}

func NewGRPC(deps DepsGRPC) (*GRPC, errors.Error) {
	if err := validator.New().Struct(deps); err != nil {
		return nil, errors.NewWithError(
			fmt.Errorf("validate deps: %w", err),
			errors.ErrInternalError,
		)
	}

	listen, err := net.Listen("tcp", ":"+deps.Config.Port)
	if err != nil {
		return nil, errors.NewWithMessage("start listener", err)
	}

	server := grpc.NewServer()

	go func() {
		deps.Logger.Info("starting grpc server")

		if serveErr := server.Serve(listen); serveErr != nil {
			deps.Logger.Error("start grpc server", slog.Any("err", serveErr))
		}
	}()

	return &GRPC{
		Server: server,
	}, nil
}

func (receiver *GRPC) Register(controllers Controllers) *GRPC {
	proto.RegisterCompilerServiceServer(receiver.Server, controllers.Compiler)

	return receiver
}
